/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.common.base.service;

import com.je.common.base.DynaBean;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.ibatis.extension.plugins.pagination.Page;
import com.je.ibatis.extension.toolkit.Constants;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public interface MetaRpcService {

    /**
     * 清空缓存
     */
    void clearMyBatisCache();

    /**
     * 插入
     *
     * @param beanMap 字段值
     * @return int 影响记录数
     */
    default DynaBean insert(DynaBean beanMap) {
        return insertByTableCode(beanMap.getStr(Constants.KEY_TABLE_CODE), beanMap);
    }

    /**
     * 插入
     *
     * @param tableCode 表名
     * @param beanMap   字段值
     * @return int 影响记录数
     */
    DynaBean insertByTableCode(String tableCode, DynaBean beanMap);

    /**
     * 批量插入
     *
     * @param list 被插入数据list
     * @return int 影响记录数
     */
    default List<DynaBean> insertBatch(List<DynaBean> list) {
        return insertBatchByTableCode(null, list);
    }

    /**
     * 批量插入
     *
     * @param tableCode 表名
     * @param list      被插入数据list
     * @return int 影响记录数
     */
    List<DynaBean> insertBatchByTableCode(String tableCode, List<DynaBean> list);

    /**
     * 修改
     *
     * @param beanMap 字段值
     * @return int 影响记录数
     */
    default DynaBean updateBean(DynaBean beanMap) {
        return update(beanMap.getTableCode(), beanMap.getPkValue(), beanMap, null);
    }

    /**
     * 修改
     *
     * @param beanMap 字段值
     * @param nativeQuery where条件
     * @return int 影响记录数
     */
    default DynaBean updateByNatieQuery(DynaBean beanMap, NativeQuery nativeQuery) {
        return update(beanMap.getTableCode(), beanMap.getPkValue(), beanMap, nativeQuery);
    }

    /**
     * 修改
     *
     * @param tableCode 表名
     * @param pkValue   主键
     * @param beanMap   字段值
     * @param nativeQuery  where条件
     * @return int 影响记录数
     */
    DynaBean update(String tableCode, String pkValue, DynaBean beanMap, NativeQuery nativeQuery);

    /**
     * 删除
     * <p> 使用条件解析器的表名 <p/>
     *
     * @param nativeQuery 条件
     * @return int 影响记录数
     */
    default int deleteByNativeQuery(NativeQuery nativeQuery) {
        return deleteByTableCodeAndNativeQuery(null, nativeQuery);
    }

    /**
     * 删除
     *
     * @param tableCode 表名
     * @param nativeQuery  条件
     * @return int 影响记录数
     */
    int deleteByTableCodeAndNativeQuery(String tableCode, NativeQuery nativeQuery);

    /**
     * 查询数据使用自定义sql
     * <p> 不分页 <p/>
     *
     * @param sql    原始sql
     * @param params sql参数数组
     * @return List
     */
    default List<Map<String, Object>> selectMap(String sql, Object... params) {
        return selectPageMapByStartAndLimit(-1, -1, sql, params);
    }

    /**
     * 查询数据使用自定义sql
     * <p> 不分页 <p/>
     *
     * @param current 第几页
     * @param size    每页数量
     * @param sql     自定义sql
     * @param params  sql参数数组
     * @return List
     */
    default List<Map<String, Object>> selectPageMapByStartAndLimit(int current, int size, String sql, Object... params) {
        return selectMapByPageAndNativeQuery(new Page<>(current, size), NativeQuery.build().sqlWithParams(sql, params != null? Arrays.asList(params):null));
    }

    /**
     * 查询数据使用自定义sql
     * <p> 不分页 <p/>
     *
     * @param nativeQuery 查询sql
     * @return List
     */
    default List<Map<String, Object>> selectMapByNativeQuery(NativeQuery nativeQuery) {
        return selectMapByPageAndNativeQuery(null, nativeQuery);
    }

    /**
     * 查询数据使用自定义sql
     *
     * @param page    分页对象
     * @param nativeQuery 查询sql
     * @return List
     */
    List<Map<String, Object>> selectMapByPageAndNativeQuery(Page page, NativeQuery nativeQuery);

    /**
     * 查询数据使用自定义sql
     *
     * @param tableCode 表名
     * @param current   第几页
     * @param size      每页数量
     * @param sql       where条件
     * @param params    sql参数数组
     * @return List
     */
    default List<DynaBean> select(String tableCode, int current, int size, String sql, Object... params) {
        return selectPageByTableCodeAndStartAndLimitAndNativeQuery(tableCode, current, size, NativeQuery.build().sqlWithParams(sql, params != null? Arrays.asList(params):null));
    }

    /**
     * 查询数据使用自定义sql
     *
     * @param tableCode 表名
     * @param page      分页对象
     * @param sql       where条件
     * @param params    sql参数数组
     * @return List
     */
    default List<DynaBean> select(String tableCode, Page page, String sql, Object... params) {
        return selectPageByPageAndNativeQuery(tableCode, page, NativeQuery.build().sqlWithParams(sql, params != null? Arrays.asList(params):null));
    }

    /**
     * 查询数据
     * <p> 不分页，使用条件解析器的表名 <p/>
     *
     * @param nativeQuery 条件
     * @return List
     */
    default List<DynaBean> selectByNativeQuery(NativeQuery nativeQuery) {
        return selectPageByTableCodeAndStartAndLimitAndNativeQuery(null, -1, -1, nativeQuery);
    }

    /**
     * 查询数据
     * <p>
     * 不分页
     *
     * @param tableCode 表名
     * @param nativeQuery  条件
     * @return List
     */
    default List<DynaBean> selectByTableCodeAndNativeQuery(String tableCode, NativeQuery nativeQuery) {
        return selectPageByTableCodeAndStartAndLimitAndNativeQuery(tableCode, -1, -1, nativeQuery);
    }

    /**
     * 查询数据
     * <p>
     * 不分页
     *
     * @param tableCode 表名
     * @param nativeQuery   条件
     * @return List
     */
    default List<DynaBean> selectByTableCodeAndNativeQueryWithColumns(String tableCode, NativeQuery nativeQuery, String columns) {
        return selectPageWithColumns(tableCode, new Page(-1, -1), nativeQuery, columns);
    }

    /**
     * 查询数据
     * <p>
     * 默认读取第一页
     *
     * @param tableCode 表名
     * @param size      每页数量
     * @param nativeQuery   条件
     * @return List
     */
    default List<DynaBean> selectPageByTableCodeAndNativeQuery(String tableCode, int size, NativeQuery nativeQuery) {
        return selectPageByTableCodeAndStartAndLimitAndNativeQuery(tableCode, 1, size, nativeQuery);
    }

    /**
     * 查询数据
     * <p>
     * 使用条件解析器的表名
     *
     * @param current 第几页
     * @param size    每页数量
     * @param nativeQuery 条件
     * @return List
     */
    default List<DynaBean> selectPageByStartAndLimitAndNativeQuery(int current, int size, NativeQuery nativeQuery) {
        return selectPageByTableCodeAndStartAndLimitAndNativeQuery(null, current, size, nativeQuery);
    }

    /**
     * 查询数据
     * <p>
     * 不使用条件解析器
     *
     * @param tableCode 表名
     * @param current   第几页
     * @param size      每页数量
     * @return List
     */
    default List<DynaBean> selectPageByStartAndLimit(String tableCode, int current, int size) {
        return select(tableCode, current, size, null);
    }

    /**
     * 查询数据
     *
     * @param tableCode 表名
     * @param current   第几页
     * @param size      每页数量
     * @param nativeQuery   条件
     * @return List
     */
    default List<DynaBean> selectPageByTableCodeAndStartAndLimitAndNativeQuery(String tableCode, int current, int size, NativeQuery nativeQuery) {
        return selectPageByPageAndNativeQuery(tableCode, new Page(current, size), nativeQuery);
    }

    /**
     * 查询数据
     *
     * @param tableCode 表名
     * @param page      分页对象
     * @param nativeQuery   条件
     * @return List
     */
    default List<DynaBean> selectPageByPageAndNativeQuery(String tableCode, Page page, NativeQuery nativeQuery) {
        return selectPageWithColumns(tableCode, page, nativeQuery, null);
    }

    /**
     * 查询数据
     *
     * @param tableCode 表名
     * @param page      分页对象
     * @param nativeQuery   条件
     * @param columns   要查询的列
     * @return List
     */
    List<DynaBean> selectPageWithColumns(String tableCode, Page page, NativeQuery nativeQuery, String columns);

    /**
     * 查询一条数据
     * <p>
     * 查询结果数量大于1 抛出异常
     *
     * @param tableCode 表名
     * @param nativeQuery   条件
     * @return List
     */
    default DynaBean selectOneByNativeQuery(String tableCode, NativeQuery nativeQuery) {
        return selectOne(tableCode, nativeQuery, null);
    }

    /**
     * 查询一条数据
     * <p>
     * 查询结果数量大于1 抛出异常
     *
     * @param tableCode 表名
     * @param nativeQuery  条件
     * @param columns   要查询的列
     * @return List
     */
    DynaBean selectOne(String tableCode, NativeQuery nativeQuery, String columns);

    /**
     * 加载功能数据
     *
     * @param funcCode 功能code
     * @param page     分页对象
     * @param sql      原始sql
     * @param params   sql参数数组
     * @return List
     */
    default List<Map<String, Object>> load(String funcCode, Page page, String sql, Object... params) {
        return loadByNativeQuery(funcCode, page, NativeQuery.build().sqlWithParams(sql, params != null? Arrays.asList(params):null));
    }

    /**
     * 加载功能数据
     *
     * @param funcCode 功能code
     * @param page     分页对象
     * @param nativeQuery  条件
     * @return List
     */
    List<Map<String, Object>> loadByNativeQuery(String funcCode, Page page, NativeQuery nativeQuery);

    /**
     * 根据主键查询数据
     *
     * @param tableCode 表名
     * @param pkValue   主键值
     * @return com.je.core.util.bean.DynaBean
     */
    default DynaBean selectOneByPk(String tableCode, String pkValue) {
        return selectOneByPkWithColumns(tableCode, pkValue, null);
    }

    /**
     * 根据主键查询数据
     *
     * @param tableCode 表名
     * @param pkValue   主键值
     * @param columns   要查询的列
     * @return com.je.core.util.bean.DynaBean
     */
    DynaBean selectOneByPkWithColumns(String tableCode, String pkValue, String columns);

    /**
     * 执行sql
     * <p>
     * in类型预处理参数，禁用数组！禁用数组！禁用数组！统一使用Collection子类，如 List Set
     *
     * @param sql    自定义sql
     * @param params sql参数数组
     * @return int 影响记录数
     */
    default int executeSql(String sql, Object... params) {
        return executeSqlByNativeQuery(NativeQuery.build().sqlWithParams(sql, params != null? Arrays.asList(params):null));
    }

    /**
     * 执行总数查询sql
     *
     * @param nativeQuery 查询sql
     * @return long count值
     */
    int executeSqlByNativeQuery(NativeQuery nativeQuery);

    /**
     * 执行总数查询sql
     *
     * @param sql    自定义sql
     * @param params sql参数数组
     * @return long count值
     */
    default long countBySql(String sql, Object... params) {
        return countByNativeQuery(NativeQuery.build().sqlWithParams(sql, params != null? Arrays.asList(params):null));
    }

    /**
     * 执行总数查询sql
     *
     * @param nativeQuery 查询sql
     * @return long count值
     */
    long countByNativeQuery(NativeQuery nativeQuery);

    /**
     * 查询数据是否存在
     * @param tableCode
     * @param pkValue
     * @return
     */
    Boolean selectDataExistsByPkValue(String tableCode, String pkValue);

}
